
#include "common_def.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"
#include <stdio.h>


#include "pinctrl.h"
#include "soc_osal.h"
#include "gpio.h"
#include "spi.h"
#include <unistd.h>


#define TASKS_TEST_TASK_STACK_SIZE    0x1000
#define TASKS_TEST_TASK_PRIO          (osPriority_t)(17)
#define TASKS_TEST_DURATION_MS        100

// #define CONFIG_SCL 13
// #define CONFIG_SDA 14


#define SHT30_I2C_ADDR           0x44  
#define SHT30_MEASURE_CMD_HIGH       0x2C06 



// 初始化软件 I2C
void sht30_init(void) {
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);
}

// I2C 起始条件
void sht30_start(void) {
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);
    usleep(5);
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_LOW);  // CONFIG_SDA 拉低
    usleep(5);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
}

// I2C 停止条件
void sht30_stop(void) {
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_LOW);  // CONFIG_SDA 拉低
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
    usleep(5);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);  // CONFIG_SCL 拉高
    usleep(5);
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);  // CONFIG_SDA 拉高
}

// I2C 发送一个字节
uint8_t sht30_send_byte(uint8_t byte) {
    for (int i = 0; i < 8; i++) {
        uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
        if (byte & 0x80) {
            uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);  // CONFIG_SDA 拉高  // 发送 1
        } else {
            uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_LOW);  // CONFIG_SDA 拉低  // 发送 0
        }
        usleep(5);
        uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);  // CONFIG_SCL 拉高
        usleep(5);
        byte <<= 1;  // 左移一位
    }

    // 读取 ACK
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);  // CONFIG_SDA 拉高 // 释放 CONFIG_SDA

    // 将 CONFIG_SDA 引脚方向切换为输入模式
    uapi_gpio_set_dir(CONFIG_SDA, GPIO_DIRECTION_INPUT);

    usleep(5);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);  // CONFIG_SCL 拉高 
    usleep(5);
    
    uint8_t ack = uapi_gpio_get_val(CONFIG_SDA);  // 读取 ACK

    // 将 CONFIG_SDA 引脚方向切换回输出模式
    uapi_gpio_set_dir(CONFIG_SDA, GPIO_DIRECTION_OUTPUT);

    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
    return ack;  // 返回 ACK 状态（0 表示 ACK，1 表示 NACK）
}

// I2C 读取一个字节
uint8_t sht30_read_byte(uint8_t ack) {
    uint8_t byte = 0;

    // 将 CONFIG_SDA 引脚方向切换为输入模式
    uapi_gpio_set_dir(CONFIG_SDA, GPIO_DIRECTION_INPUT);

    for (int i = 0; i < 8; i++) {
        uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低
        usleep(5);
        uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);  // CONFIG_SCL 拉高
        usleep(5);

        byte <<= 1;  // 左移一位
        if (uapi_gpio_get_val(CONFIG_SDA)) {
            byte |= 0x01;  // 读取 1
        }
    }

    // 发送 ACK/NACK
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低

    // 将 CONFIG_SDA 引脚方向切换为输出模式
    uapi_gpio_set_dir(CONFIG_SDA, GPIO_DIRECTION_OUTPUT);

    if (ack) {
        uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);  // 发送 NACK
    } else {
        uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_LOW);  // 发送 ACK
    }

    usleep(5);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);  // CONFIG_SCL 拉高
    usleep(5);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_LOW);  // CONFIG_SCL 拉低

    return byte;
}


// CRC-8 校验函数
uint8_t crc8(const uint8_t *data, uint8_t len) {
    uint8_t crc = 0xFF;  // 初始值
    for (uint8_t i = 0; i < len; i++) {
        crc ^= data[i];  // 异或操作
        for (uint8_t bit = 0; bit < 8; bit++) {
            if (crc & 0x80) {
                crc = (crc << 1)^0x31;  // 多项式 0x31
            } else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

// 向 SHT30 发送开始测量命令
void sht30_start_measurement(void) {
    sht30_start();
    sht30_send_byte(SHT30_I2C_ADDR << 1);  // 发送设备地址（写模式）
    sht30_send_byte(SHT30_MEASURE_CMD_HIGH >> 8);  // 发送命令高字节
    sht30_send_byte(SHT30_MEASURE_CMD_HIGH & 0xFF);  // 发送命令低字节
    sht30_stop();
}

// 从 SHT30 读取温湿度数据
int sht30_read_data(float *temperature, float *humidity) {
    uint8_t data[6];  // SHT30 返回 6 字节数据（温度 + 湿度 + CRC）

    sht30_start();
    sht30_send_byte((SHT30_I2C_ADDR << 1) | 0x01);  // 发送设备地址（读模式）

    // 读取 6 字节数据
    for (int i = 0; i < 6; i++) {
        data[i] = sht30_read_byte(i == 5);  // 最后一个字节发送 NACK
    }
    sht30_stop();

    // 校验 CRC
    if (crc8(data, 2) != data[2] || crc8(data + 3, 2) != data[5]) {
        return -1;  // CRC 校验失败
    }

    // 解析温度数据
    uint16_t temp_raw = (data[0] << 8) | data[1];
    *temperature = -45 + 175 * (float)temp_raw / 65535.0f;

    // 解析湿度数据
    uint16_t humi_raw = (data[3] << 8) | data[4];
    *humidity = 100 * (float)humi_raw / 65535.0f;

    return 0;  // 读取成功

}

void sht30_Port_Init(void)
{
 // 配置 CONFIG_SDA 和 CONFIG_SCL 引脚为开漏输出模式

    uapi_pin_set_mode(CONFIG_SCL, PIN_MODE_0);
    uapi_gpio_set_dir(CONFIG_SCL, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SCL, GPIO_LEVEL_HIGH);

    uapi_pin_set_mode(CONFIG_SDA, PIN_MODE_0);
    uapi_gpio_set_dir(CONFIG_SDA, GPIO_DIRECTION_OUTPUT);
    uapi_gpio_set_val(CONFIG_SDA, GPIO_LEVEL_HIGH);

}

